package com.power.sifa.approve.controller;

import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.plf.common.domain.PageDataResponse;
import com.plf.common.domain.ResponseDTO;
import com.plf.common.domain.YesNo;
import com.plf.common.utils.ExcelUtil;
import com.power.flowable.api.IPersonalFeign;
import com.power.sifa.approve.api.IApl_mainFeign;
import com.power.sifa.approve.model.*;
import com.power.sifa.approve.model.enumeration.St_admreview;
import com.power.sifa.approve.model.enumeration.St_apply;
import com.power.sifa.approve.model.enumeration.Tp_procmaterial;
import com.power.sifa.approve.model.enumeration.Tp_proctype;
import com.power.sifa.approve.model.pageInfo.Apl_mainPageInfo;
import com.power.sifa.approve.model.pojo.bo.CaseBaseExcelBO;
import com.power.sifa.approve.service.*;
import com.power.sifa.net.model.enumeration.Tp_matter;
import com.power.sifa.supervise.model.Apl_supervise;
import com.power.sifa.supervise.service.Apl_superviseService;
import com.power.sifa.util.ExcelCommonUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;



/**
 *   业务申请主表控制器
 */

@Slf4j
@RestController
@Api(value = "Apl_mainController",tags={"业务申请主表"})
public class Apl_mainController implements IApl_mainFeign{

    @Resource
    private Apl_mainService apl_mainService;
    @Resource
    private Apl_admreviewService apl_admreviewService;
    @Resource
    private Apl_superviseService apl_superviseService;
    @Resource
    private Apl_applicantService apl_applicantService;
    @Resource
    private Apl_targetService apl_targetService;
    @Resource
    private Apl_thirdperService apl_thirdperService;
    @Resource
    private Apl_agentService apl_agentService;
    @Resource
    private Apl_admre_auditService apl_admre_auditService;
    @Resource
    private IPersonalFeign iPersonalFeign;
    @Resource
    private Aprv_process_materialsService apl_process_materialsService;

    @Override
    @ApiOperation("查询业务申请主表分页列表")
    @SaCheckPermission("apl_main_list")
    public ResponseDTO list(Apl_mainPageInfo pageInfo) {
        Assert.notNull(pageInfo, "pageInfo参数不能为空");
        Page<Apl_main> page = this.apl_mainService.findAll(pageInfo);
        List list = new ArrayList();
        if (!page.isEmpty()) {
            for (Apl_main apl_main : page) {
                apl_main.geneText();
                list.add(apl_main);
            }
        }
        PageDataResponse p = new PageDataResponse(list, page.getTotalElements(), page.getSize(), pageInfo.getPageNumber()<=1 ? 1 : pageInfo.getPageNumber());
        return ResponseDTO.succData(p);
    }

    @Override
    @ApiOperation("查看业务申请主表")
    @SaCheckPermission("apl_main_view")
    public ResponseDTO view(String id) {
        Assert.notNull(id, "id不能为空");
        Apl_main apl_main  = apl_mainService.getById(id);
        if (apl_main != null) {
            apl_main.geneText();
        }
        return ResponseDTO.succData(apl_main);
    }

    @Override
    @ApiOperation("删除业务申请主表")
    @SaCheckPermission("apl_main_del")
    public ResponseDTO delete(String id) {
        Assert.notNull(id, "id不能为空");
        apl_mainService.removeById(id);
        return ResponseDTO.succ();
    }

    @Override
    @ApiOperation("保存或修改业务申请主表")
    @SaCheckPermission("apl_main_save")
    public ResponseDTO save(Apl_main apl_main) {
        Assert.notNull(apl_main, "apl_main不能为空");
        apl_mainService.saveOrUpdate(apl_main);
        return ResponseDTO.succ();
    }

    @Override
    @ApiOperation(value="批量删除业务申请主表")
    @SaCheckPermission("apl_main_del")
    public ResponseDTO batchDel(String ids) {
        Assert.isTrue(StringUtils.hasText(ids), "ids不能为空");
        List<Integer> list = Arrays.asList(ids.split(",")).stream().map(s -> Integer.parseInt(s.trim())).collect(Collectors.toList());
        apl_mainService.removeByIds(list);
        return ResponseDTO.succ();
    }

    @Override
    @ApiOperation(value="导出excel")
    @SaCheckPermission("apl_main_list")
    public void output(HttpServletResponse response, Apl_mainPageInfo pageInfo) {
        Assert.notNull(pageInfo, "pageInfo不能为空");
        String title = "业务申请主表";
        String[] heads = {"毫秒+nanoid","申请流水号","申请标题","申请类型id","申请来源","录入人id","录入人","录入/拟受理单位id","录入/拟受理单位","创建时间","最后修改时间","提交时间","受理号","受理时间","受理人id","受理人","受理部门id","受理部门","受理单位id","受理单位","受理单位行政区划id","办结时间","表单id","流程实例id","状态","办结时限环节组id"};
        String[] fields = {"id","applycode","title","matid","source","reguserid","regusername","regsectionid","regsectionname","createtime","updatetime","subtime","acceptcode","accepttime","acceptuserid","acceptusername","acceptdeptid","acceptdeptname","acceptsectionid","acceptsectionname","acceptadid","finishtime","formid","instid","status","scatid"};
        Page<Apl_main> page = this.apl_mainService.findAll(pageInfo);
        ExcelUtil.exportXls(title, heads, fields, page.getContent(), response);
    }

    @Override
    @ApiOperation(value="导出excel模板")
    public void exportExcelTemplate(HttpServletResponse response) {
        String title = "业务申请主表";
        //id自增或list从表可自行删除，需与导入项一致
        String[] heads = {"毫秒+nanoid","申请流水号","申请标题","申请类型id","申请来源","录入人id","录入人","录入/拟受理单位id","录入/拟受理单位","创建时间","最后修改时间","提交时间","受理号","受理时间","受理人id","受理人","受理部门id","受理部门","受理单位id","受理单位","受理单位行政区划id","办结时间","表单id","流程实例id","状态","办结时限环节组id"};
        ExcelUtil.exportXls(title, heads, null, null, response);
    }

	@Override
	@ApiOperation(value="导入excel")
	public ResponseDTO importExcel(MultipartFile file) throws IOException {
        Assert.notNull(file, "file不能为空");
        //id自增或list从表可自行删除，需与下载的模板中导入项一致
        String[] fields = {"id","applycode","title","matid","source","reguserid","regusername","regsectionid","regsectionname","createtime","updatetime","subtime","acceptcode","accepttime","acceptuserid","acceptusername","acceptdeptid","acceptdeptname","acceptsectionid","acceptsectionname","acceptadid","finishtime","formid","instid","status","scatid"};
        List<Apl_main> list = (List<Apl_main>)ExcelUtil.Import(fields, file, Apl_main.class);
        if(!CollectionUtils.isEmpty(list)) {
            this.apl_mainService.saveAll(list);
        }
        return ResponseDTO.succ();
	}

    @Override
    public ResponseDTO getByInstid(String instid) {
        return ResponseDTO.succData(this.apl_mainService.getByInstid(instid));
    }

    @Override
    public ResponseDTO getByInstids(List<String> instids) {
        return ResponseDTO.succData(this.apl_mainService.getByInstids(instids));
    }

    @Override
    public ResponseDTO updateScatid(String instid, String scatid) {
        this.apl_mainService.updateScatid(instid, scatid);
        return ResponseDTO.succ();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseDTO updateStatus(String id, Integer status) {
        try {
            // 如果更新的状态等于结束, 那么同时把办结时间也更新了
            if(status == St_apply.FINISH) {
                String finishtime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
                this.apl_mainService.updateStatusAndFinishtime(id, St_apply.FINISH, finishtime);
            } else {
                this.apl_mainService.updateStatus(id, status);
            }
            return ResponseDTO.succ();
        } catch (Exception e) {
            log.error("/apl_main/updateStatus 更新申请主表状态失败 ->  msg[{}]", e.getMessage());
            return ResponseDTO.wrap(500, "更新申请主表状态失败 -> " + e.getMessage());
        }
    }

    @Override
    public ResponseDTO queryUserTreeByDepartids(List<String> departList) {
        try {
            return ResponseDTO.succData(this.apl_mainService.queryUserTreeByDepartids(departList));
        } catch (Exception e) {
            e.printStackTrace();
            log.error("查询业务分派树失败 queryDepartTree ->  msg[{}]", e.getMessage());
            return ResponseDTO.wrap(500, "查询业务分派树失败");
        }
    }

    @Override
    public ResponseDTO queryBusineTree(String applyid, String departid) {
        try {
            return ResponseDTO.succData(this.apl_mainService.queryBusineTree(applyid, departid));
        } catch (Exception e) {
            e.printStackTrace();
            log.error("查询业务分派树失败 queryBusineTree ->  msg[{}]", e.getMessage());
            return ResponseDTO.wrap(500, "查询业务分派树失败");
        }
    }

    @Override
    public ResponseDTO queryTaskidByApplyid(String applyid) {
        Apl_main main = this.apl_mainService.getById(applyid);
        if(main == null) {
            return ResponseDTO.wrap(500, "查询主表业务对象失败");
        }
        ResponseDTO res = this.iPersonalFeign.queryTaskidByInstid(main.getInstid());
        if(0 != res.getCode()) {
            return ResponseDTO.wrap(500, res.getMsg());
        }
        return ResponseDTO.succData(res.getData());
    }

    @Override
    public ResponseDTO querySecondUseridByInstid(String instid) {
        try {
            Apl_main mainObj = this.apl_mainService.getByInstid(instid);
            if(null == mainObj) {
                return ResponseDTO.wrap(500, "queryAdmerviewByInstid 主表对象为空");
            }

            // 根据matid判断事项协办人
            switch (mainObj.getMatid()) {
                case Tp_matter.PUB_ADMREVIEW: {
                    Apl_admreview admreObj = this.apl_admreviewService.getById(mainObj.getId());
                    if(null == admreObj) {
                        return ResponseDTO.wrap(500, "querySecondUseridByInstid 业务主表对象为空");
                    }
                    return ResponseDTO.succData(admreObj.getHearsecondid());
                }
                case Tp_matter.PUB_SUPERVISE: {
                    Apl_supervise supObj = this.apl_superviseService.getById(mainObj.getId());
                    if(null == supObj) {
                        return ResponseDTO.wrap(500, "querySecondUseridByInstid 业务主表对象为空");
                    }
                    return ResponseDTO.succData(supObj.getSecondid());
                }
                default: {
                    log.error("未查询到事项对应协办人 matid -> {}", mainObj.getMatid());
                }
            }
            return ResponseDTO.wrap(500, "未查询到事项对应协办人");
        } catch (Exception e) {
            e.printStackTrace();
            log.error("queryAdmerviewByInstid 根据instid查询业务主表信息失败 ->  msg[{}]", e.getMessage());
            return ResponseDTO.wrap(500, "根据instid查询业务主表信息失败 ->" + e.getMessage());
        }

    }

    @Override
    public void exportAllCase(HttpServletResponse response) {
        List<Apl_main> endCaseList = this.apl_mainService.getListByStatus(St_apply.COMPLETELIST);
        List<CaseBaseExcelBO> excelList = new ArrayList<CaseBaseExcelBO>();
        if (CollectionUtil.isNotEmpty(endCaseList)) {
            // 查询当前的流程详情信息
            List<String> applyidist = endCaseList.stream().map(Apl_main::getId).collect(Collectors.toList());
            // 查询行政复议表数据
            List<Apl_admreview> admreviewList = this.apl_admreviewService.findAdmreviewList(applyidist);
            // 查询
            endCaseList.forEach(el -> {
                el.geneText();
                final String applyid = el.getId();
                Apl_admreview admreObj = admreviewList.stream().filter(admreview -> admreview.getId().equals(applyid)).findFirst().orElse(null);
                if (ObjectUtil.isNotNull(admreObj)) {
                    admreObj.geneText();
                }
                // 查询申请人表数据
                List<Apl_applicant> applicantList = this.apl_applicantService.getApplicantByApplyid(applyid);
                // 查询被申请人表数据
                List<Apl_target> targetList = this.apl_targetService.getTargetListByApplyid(applyid);
                // 查询第三人表数据
                List<Apl_thirdper> thirdperList = this.apl_thirdperService.getThirdListByApplyid(applyid);
                // 查询代理人表数据
                List<Apl_agent> agentList = this.apl_agentService.getAgentByApplyid(applyid);
                // 行政复议审批表数据
                List<Apl_admre_audit> auditList = this.apl_admre_auditService.listAdmreAuditByApplyid(applyid);
                // 查询全部的材料
                List<Aprv_process_materials> materialsList = this.apl_process_materialsService.getAllMaterialByApplyId(applyid);
                // 案号
                String acceptcode = el.getAcceptcode();
                // 案件来源
                String source = el.getSource_text();
                // 收到时间
                String receiveTime = el.getSubtime();
                // 申请人
                String applyname = "";
                // 送达地址
                String applyAddress = "";
                if (CollUtil.isNotEmpty(applicantList)) {
                    applyname = applicantList.stream().map(Apl_applicant::getName).collect(Collectors.joining(","));
                    applyAddress = applicantList.stream().map(Apl_applicant::getAddr).collect(Collectors.joining(","));
                }
                // 是否需要补正
                String needAdd = "";
                if (CollUtil.isNotEmpty(auditList)) {
                    if (auditList.stream().filter(audit -> ObjectUtil.isNotNull(audit.getStatus())).anyMatch(audit -> audit.getStatus().equals(Tp_proctype.ACCEPT_APPEND))) {
                        needAdd = "是";
                    }
                }
                // 代理人及联系电话
                String agentPhone = "";
                if (CollUtil.isNotEmpty(agentList)) {
                    agentPhone = agentList.stream().map(agent -> agent.getName() + "(" + agent.getTel() + ")").collect(Collectors.joining(","));
                }

                // 行政复议请求类型
                String applyType = "";
                // 类别
                String caseType = "";
                // 简易程序/普
                String proctype = "";
                // 期满时间
                String quedate = "";
                // 是否属于案前调解
                String isBeforeCaseEnd = "";
                if (ObjectUtil.isNotNull(admreObj)) {
                    applyType = admreObj.getPrtype_text();
                    caseType = admreObj.getMgrcate();
                    proctype = admreObj.getProctype_text();
                    quedate = admreObj.getQuedate();
                    isBeforeCaseEnd = admreObj.getStatus().equals(St_admreview.MEDIATE) ? "是" : "否";
                }
                // 争议标的
                String disputeInfo = "";

                // 被申请人
                String targetName = "";
                // 被申请人联系人
                String targetContactName = "";
                if (CollUtil.isNotEmpty(targetList)) {
                    targetName = targetList.stream().map(Apl_target::getName).collect(Collectors.joining(","));
                    targetContactName = targetList.stream().map(Apl_target::getManager).collect(Collectors.joining(","));
                }
                // 被申请人答复情况
                String targetReplyInfo = "";
                if (ObjectUtil.isNotNull(admreObj)) {
                    targetReplyInfo = admreObj.getIstargetreply().equals(YesNo.YES) ? "是" : "否";
                }

                // 第三人
                String thirdName = "";
                // 第三人联系人
                String thirdContactName = "";
                if (CollUtil.isNotEmpty(thirdperList)) {
                    thirdName = thirdperList.stream().map(Apl_thirdper::getName).collect(Collectors.joining(","));
                    thirdContactName = thirdperList.stream().map(Apl_thirdper::getManager).collect(Collectors.joining(","));
                }
                // 第三人答复情况
                String thirdReplyInfo = "";

                // 受理时间
                String acceptTime = el.getAccepttime();
                // 受理处理结果
                String acceptResult = "";
                if (CollUtil.isNotEmpty(auditList)) {
                    if (auditList.stream().filter(audit -> ObjectUtil.isNotNull(audit.getStatus())).anyMatch(audit -> audit.getStatus().equals(Tp_proctype.ACCEPT_ACCEPT))) {
                        acceptResult = "受理";
                    }
                    if (auditList.stream().filter(audit -> ObjectUtil.isNotNull(audit.getStatus())).anyMatch(audit -> audit.getStatus().equals(Tp_proctype.ACCEPT_NOACCEPT))) {
                        acceptResult = "不予受理";
                    }
                    if (auditList.stream().filter(audit -> ObjectUtil.isNotNull(audit.getStatus())).anyMatch(audit -> audit.getStatus().equals(Tp_proctype.ACCEPT_RESULT))) {
                        acceptResult = "撤回";
                    }
                    if (auditList.stream().filter(audit -> ObjectUtil.isNotNull(audit.getStatus())).anyMatch(audit -> audit.getStatus().equals(Tp_proctype.MATER_MEDIATE))) {
                        acceptResult = "调解";
                    }
                }
                // 受理承办人
                String acceptUser = el.getAcceptusername();
                // TODO: 转送审理时间
                String toHearDate = "";
                // 审理承办人
                String hearUser = "";
                if (ObjectUtil.isNotNull(admreObj)) {
                    hearUser = admreObj.getHearfirstname();
                }
                // TODO: 结案时间
                String hearEndDate = "";

                // 审理结果 决定类型
                String hearResult = "";
                if (ObjectUtil.isNotNull(admreObj)) {
                    hearResult = admreObj.getDecisiontype_text();
                }

                // 是否听取意见
                String isHearOpinion = "";

                // 是否组织听证
                String isHearEvidence = "";
                if (CollUtil.isNotEmpty(auditList)) {
                    if (auditList.stream().filter(audit -> ObjectUtil.isNotNull(audit.getStatus())).anyMatch(audit -> audit.getStatus().equals(Tp_proctype.HEAR_HEARING))) {
                        isHearEvidence = "是";
                    }
                }

                // 是否邀请复议
                String isHearRepeat = "";

                // 是否组织调解
                String isHearMediation = "";
                if (CollUtil.isNotEmpty(auditList)) {
                    if (auditList.stream().filter(audit -> ObjectUtil.isNotNull(audit.getStatus())).anyMatch(audit -> audit.getStatus().equals(Tp_proctype.MATER_MEDIATE))) {
                        isHearMediation = "是";
                    }
                    if (auditList.stream().filter(audit -> ObjectUtil.isNotNull(audit.getStatus())).anyMatch(audit -> audit.getStatus().equals(Tp_proctype.HEAR_MEDIATE))) {
                        isHearMediation = "是";
                    }
                }

                // 是否制发行政复议意见书
                String isMakeOpinion = "";
                if (CollUtil.isNotEmpty(materialsList)) {
                    if (materialsList.stream().filter(material -> ObjectUtil.isNotNull(material.getMattype())).anyMatch(material -> material.getMattype().equals(Tp_procmaterial.ARRIVE_OPINION))) {
                        isMakeOpinion = "是";
                    }
                }
                // 履行期限届满时间
                String performLimitDate = "";

                // 被申请人是否书面反馈及反馈时间
                String targetReplyOffice = "";

                // 是否责令履行
                String isPerform = "";
                if (CollUtil.isNotEmpty(auditList)) {
                    if (auditList.stream().filter(audit -> ObjectUtil.isNotNull(audit.getStatus())).anyMatch(audit -> audit.getStatus().equals(Tp_proctype.EXECUTE_PERFORM))) {
                        isPerform = "是";
                    }
                }

                // 是否制发政务处分建议书
                String isMakePunish = "";
                if (CollUtil.isNotEmpty(materialsList)) {
                    if (materialsList.stream().filter(material -> ObjectUtil.isNotNull(material.getMattype())).anyMatch(material -> material.getMattype().equals(Tp_procmaterial.ARRIVE_PUNISH))) {
                        isMakePunish = "是";
                    }
                }
                // 是否提起诉讼
                String isLitigation = "";

                // 是否答辩
                String isDefense = "";

                // 开庭时间/出庭人员
                String court = "";

                // 一审裁判结果
                String firstJudgment = "";

                // 是否提交上诉状
                String isAppeal = "";

                // 二审裁判结果
                String secondJudgment = "";

                // 是否申请再审
                String isReCharge = "";

                CaseBaseExcelBO excelBO =  CaseBaseExcelBO.builder().acceptcode(acceptcode).source(source).receiveTime(receiveTime).applyname(applyname).needAdd(needAdd).agentPhone(agentPhone)
                        .applyAddress(applyAddress).applyType(applyType).caseType(caseType).disputeInfo(disputeInfo).proctype(proctype).quedate(quedate).isBeforeCaseEnd(isBeforeCaseEnd).targetName(targetName)
                        .targetContactName(targetContactName).targetReplyInfo(targetReplyInfo).thirdName(thirdName).thirdContactName(thirdContactName).thirdReplyInfo(thirdReplyInfo).acceptTime(acceptTime)
                        .acceptResult(acceptResult).acceptUser(acceptUser).toHearDate(toHearDate).hearUser(hearUser).hearEndDate(hearEndDate).hearResult(hearResult).isHearOpinion(isHearOpinion)
                        .isHearEvidence(isHearEvidence).isHearRepeat(isHearRepeat).isHearMediation(isHearMediation).isMakeOpinion(isMakeOpinion).performLimitDate(performLimitDate).targetReplyOffice(targetReplyOffice)
                        .isPerform(isPerform).isMakePunish(isMakePunish).isLitigation(isLitigation).isDefense(isDefense).court(court).firstJudgment(firstJudgment).isAppeal(isAppeal).secondJudgment(secondJudgment).isReCharge(isReCharge).build();


                excelList.add(excelBO);
            });

        }
        ExcelCommonUtil.export(response, "行政复议案件", excelList, CaseBaseExcelBO.class);
    }

}
